package com.yan.test.work.testpaging3.net;



import android.content.Context;
import android.os.Build;
import android.text.TextUtils;


import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * http请求工具
 * Created by Robin on 15/6/27.
 */
public class HttpUtil {

    //本地缓存
    public static final String KEY_LOCAL_TOKEN = "token";
    //登录主UserId
    public static final String KEY_LOCAL_USER_ID = "user_id";
    //子产品UserId
    public static final String KEY_CHILD_LOCAL_USER_ID = "child_user_id";
    //token
    private static final String KEY_HEADER_TOKEN = "powerfulSilenceClone";
    //client-id
    private static final String KEY_HEADER_CLIENT_ID = "chineseDormitory";
    //USER-ID
    private static final String KEY_HEADER_USER_ID = "untrueShoppingBestDigestInformation";
    //currentUserId
    private static final String KEY_HEADER_CURRENT_USER_ID = "northBehaviourTibetanSmellyGame";
    //channel",
    private static final String KEY_HEADER_CHANNEL = "pleasantAgreement";
    //versionName",
    private static final String KEY_HEADER_VERSION_NAME = "dirtySkillAnxiousMoreAunt";
    //versionCode",
    private static final String KEY_HEADER_VERSION_CODE = "bentDelightedStep";
    //device-id",
    private static final String KEY_HEADER_DEVICE_ID = "regularPityForeignDust";
    //deviceId
    private static final String KEY_HEADER_DEVICEID = "socialistRadioactiveMoreLot";
    //imei",
    private static final String KEY_HEADER_IMEI = "livelyReadyLazyPrize";
    //mulFlag",
    private static final String KEY_HEADER_MUL_FLAG = "tinySpiritSwimming";
    //v-flag",
    private static final String KEY_HEADER_V_FLAG = "someMaidRoundInformation";
    //systemMode
    private static final String KEY_SYSTEM_MODE = "likelyBehaviourForeignSilence";
    //ip
    private static final String KEY_IP = "beautifulRightRegularChain";
    //googleMobileNo
    private static final String KEY_GOOGLE_MOBILENO = "britishClassicalFoxGoat";
    //googleGaid
    private static final String KEY_GOOGLE_GAID = "troublesomeYouIncorrectMessyTomorrow";
    //googleUserAgent
    private static final String KEY_GOOGLE_USER_AGENT = "funnyExtraordinaryActor";

    public static final String KEY_HEADER_AGENT = "User-Agent";
    public static final String KEY_HEADER_AGENT_VALUE = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36";
    private final Context context;

    private OkHttpClient formHttpClient;
    private OkHttpClient fileHttpClient;

    private static HttpUtil httpUtil;


    /**
     * 获取对象实例
     *
     * @return HttpUtil实例
     */
    public static HttpUtil getInstance(Context context) {
        HttpUtil instance = httpUtil;
        if (httpUtil == null) {
            synchronized (HttpUtil.class) {
                if (instance == null) {
                    instance = new HttpUtil(context);
                    httpUtil = instance;
                }
            }
        }
        return instance;
    }
    //header
    private Request.Builder addHeaders(Request.Builder builder){
        return builder;
    }


    //公共参数
    private RequestParams commomArg(){
        RequestParams params = new RequestParams();
        return params;
    }

    private HttpUtil(Context context) {
        this.context = context;
        if (formHttpClient == null) {
            formHttpClient = new OkHttpClient.Builder()
                    .cookieJar(new CookieManger(context))
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .sslSocketFactory(HttpsFactory.createSSLSocketFactory(), new HttpsFactory.TrustAllManager())
                    .hostnameVerifier(new HttpsFactory.TrustAllHostnameVerifier())
                    .build();
        }

        if(fileHttpClient == null){
            fileHttpClient = new OkHttpClient.Builder()
                    .cookieJar(new CookieManger(context))
                    .connectTimeout(120, TimeUnit.SECONDS)
                    .readTimeout(120, TimeUnit.SECONDS)
                    .writeTimeout(120, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .sslSocketFactory(HttpsFactory.createSSLSocketFactory(), new HttpsFactory.TrustAllManager())
                    .hostnameVerifier(new HttpsFactory.TrustAllHostnameVerifier())
                    .build();
        }
    }

    /**
     * @return OkHttpClient
     */
    public OkHttpClient getFormHttpClient() {
        return formHttpClient;
    }

    /**
     * Http GET请求
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param params   请求参数
     * @param callBack 请求结果处理
     */
    public void get(Context context, String url, RequestParams params, Callback callBack) {
        log("GET请求：" + url);
        if (params != null) {
            log("请求参数：" + params.toString());
        } else {
            log("请求参数：" + "null");
            params = new RequestParams();
        }
//        HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder();
        StringBuffer sb = new StringBuffer(url);
        sb.append("?");
        for (String key : params.urlParams.keySet()) {
            String para = "";
            try {
                para = URLEncoder.encode(params.urlParams.get(key), "utf-8");
                sb.append(key).append("=").append(para).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

//            builder.addQueryParameter(key , params.urlParams.get(key));

        }

        log("访问URL：" + sb.toString());
        HttpUrl.Builder builder = HttpUrl.parse(sb.toString()).newBuilder();
        HttpUrl httpUrl = builder.build();
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(httpUrl)
                .get()
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    /**
     * Http POST请求
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param params   请求参数
     * @param callBack 请求结果处理
     */
    public void post(Context context, boolean isChild ,String url, RequestParams params, Callback callBack) {
        log("POST请求：" + url);
        params.putAll(commomArg());
        if (params != null) {
            log("请求参数：" + params.toString());
        } else {
            log("请求参数：" + "null");
            params = new RequestParams();
        }
        FormBody.Builder bodyBuilder = new FormBody.Builder();
        if (params != null) {

            ConcurrentHashMap<String, String> urlParams = params.urlParams;
            for (String key : urlParams.keySet()) {
                bodyBuilder.add(key, urlParams.get(key));
            }
        }
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .post(bodyBuilder.build())
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }


    public Response asyncPost(Context context ,String url, RequestParams params){
        return asyncPost( context,  true , url,  params);
    }

    public Response asyncPost(Context context, boolean isChild ,String url, RequestParams params) {
        try {
            log("POST请求：" + url);
            params.putAll(commomArg());
            if (params != null) {
                log("请求参数：" + params.toString());
            } else {
                log("请求参数：" + "null");
                params = new RequestParams();
            }
            FormBody.Builder bodyBuilder = new FormBody.Builder();
            if (params != null) {

                ConcurrentHashMap<String, String> urlParams = params.urlParams;
                for (String key : urlParams.keySet()) {
                    bodyBuilder.add(key, urlParams.get(key));
                }
            }
            Request.Builder requestBuilder = new Request.Builder();
            addHeaders(requestBuilder);
            Request request = requestBuilder
                    .url(url)
                    .post(bodyBuilder.build())
                    .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
            Call call = formHttpClient.newCall(request);

            return call.execute();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Http POST请求 提交json
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param entity   请求参数
     * @param callBack 请求结果处理
     */
    public void postJson(Context context, String url, String entity, Callback callBack) {
        log("postJson：" + url);
        if (entity != null) {
            log("请求参数：" + entity);
        } else {
            log("请求参数：" + "null");
        }
        String contentType = "application/json";
        RequestBody requestBody = FormBody.create(MediaType.parse(contentType), entity);
        Request.Builder requestBuilder = new Request.Builder();
        requestBuilder
                .url(url)
                .post(requestBody)
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE);
        addHeaders(requestBuilder);
        requestBuilder.addHeader("Content-Type",contentType);
        requestBuilder.addHeader("Accept",contentType);

//        requestBuilder.addHeader("token", "H4sIAAAAAAAAACvJTMxLsjQ1MlE2NLU0MDE3NTMzMrWwAAD6EpJaFwAAAA==");
        Request request = requestBuilder.build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    /**
     * Http PUT请求
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param params   请求参数
     * @param callBack 请求结果处理
     */
    public void put(Context context, String url, RequestParams params, Callback callBack) {
        log("PUT请求：" + url);
        if (params != null) {
            log("请求参数：" + params.toString());
        } else {
            log("请求参数：" + "null");
            params = new RequestParams();
        }
        // 设置是否使用json格式传递参数
        FormBody.Builder bodyBuilder = new FormBody.Builder();
        ConcurrentHashMap<String, String> urlParams = params.urlParams;
        for (String key : urlParams.keySet()) {
            bodyBuilder.add(key, urlParams.get(key));
        }
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .put(bodyBuilder.build())
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    /**
     * Http PUT请求 提交json
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param entity   请求参数
     * @param callBack 请求结果处理
     */
    public void putJson(Context context, String url, String entity, Callback callBack) {
        log("putJson：" + url);
        if (entity != null) {
            log("请求参数：" + entity);
        } else {
            log("请求参数：" + "null");
        }

        String contentType = "application/json";
        RequestBody requestBody = FormBody.create(MediaType.parse(contentType), entity);
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .put(requestBody)
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    /**
     * Http DELETE请求 提交json
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param entity   请求参数
     * @param callBack 请求结果处理
     */
    public void deleteJson(Context context, String url, String entity, Callback callBack) {
        log("deleteJson：" + url);
        if (entity != null) {
            log("请求参数：" + entity);
        } else {
            log("请求参数：" + "null");
        }
        String contentType = "application/json";
        RequestBody requestBody = FormBody.create(MediaType.parse(contentType), entity);
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .delete(requestBody)
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    /**
     * Http DELETE请求
     *
     * @param context  用于记录该请求所属context，方便取消该请求
     * @param url      请求地址
     * @param callBack 请求结果处理
     */
    public void delete(Context context, String url, Callback callBack) {
        log("DELETE请求：" + url);
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .delete()
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = formHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    /**
     * post上传文件
     *
     * @param context
     * @param url
     * @param paraMap
     * @param fileMap
     * @param callback
     */
    public void formUpload(Context context, String url, Map<String, String> paraMap, Map<String, List<String>> fileMap, Callback callback) {
        log("upload请求：" + url);
        if (paraMap != null && fileMap != null) {
            log("请求参数：" + paraMap.toString() + ":" + fileMap);
        } else {
            log("请求参数：" + "null");
            paraMap = new HashMap<>();
            fileMap = new HashMap<>();
        }
        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
        for (String key : paraMap.keySet()) {
            bodyBuilder.addFormDataPart(key, paraMap.get(key));
        }
        for (String filekey : fileMap.keySet()) {
            for (String fileStr : fileMap.get(filekey)) {
                File file = new File(fileStr);
                bodyBuilder.addFormDataPart(filekey, file.getName(), RequestBody.create(MediaType.parse(getMIMEType(file)), file));

            }
        }
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .post(bodyBuilder.build())
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = fileHttpClient.newCall(request);
        call.enqueue(callback);
    }


    public void formUpload(Context context, String url, File file, Callback callback) {
        log("upload请求：" + url);
        log("请求参数：" + "file" + ":" + file.getAbsolutePath());
        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
        bodyBuilder.setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse(getMIMEType(file)), file));
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .post(bodyBuilder.build())
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = fileHttpClient.newCall(request);
        call.enqueue(callback);
    }


    public void formUpload(Context context,String url, RequestParams params ,Map<String , File> fileMap , Callback callback) {
        formUpload( context,  true , url,  params , fileMap ,  callback);
    }

    public void formUpload(Context context, boolean isChild ,String url, RequestParams params ,Map<String , File> fileMap , Callback callback) {
        log("upload请求：" + url);
        params.putAll(commomArg());
        if (params != null) {
            log("请求参数：" + params.toString());
        } else {
            log("请求参数：" + "null");
            params = new RequestParams();
        }
        if (fileMap != null) {
            log("文件参数：" + fileMap.toString());
        } else {
            log("文件参数：" + "null");
            fileMap = new HashMap<>();
        }
        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
        bodyBuilder = bodyBuilder.setType(MultipartBody.FORM);
        if(params != null){
            ConcurrentHashMap<String, String> urlParams = params.urlParams;
            for (String key : urlParams.keySet()) {
                bodyBuilder.addFormDataPart(key, urlParams.get(key));
            }
        }
        if(fileMap!=null){
            for (String key : fileMap.keySet()) {
                bodyBuilder.addFormDataPart(key, fileMap.get(key).getName(), RequestBody.create(MediaType.parse(getMIMEType(fileMap.get(key))), fileMap.get(key)));
            }
        }
        Request.Builder requestBuilder = new Request.Builder();
        addHeaders(requestBuilder);
        Request request = requestBuilder
                .url(url)
                .post(bodyBuilder.build())
                .addHeader(KEY_HEADER_AGENT, KEY_HEADER_AGENT_VALUE).build();
        Call call = fileHttpClient.newCall(request);
        call.enqueue(callback);
    }


    private static void log(String msg) {
        L.v(HttpUtil.class, msg);
    }


    private String getMIMEType(File file) {
        String type = "*/*";
        String fName = file.getName();
// 获取后缀名前的分隔符"."在fName中的位置。
        int dotIndex = fName.lastIndexOf(".");
        if (dotIndex < 0) {
            return type;
        }
        /* 获取文件的后缀名 */
        String end = fName.substring(dotIndex + 1, fName.length()).toLowerCase();
        if (end == "")
            return type;
// 在MIME和文件类型的匹配表中找到对应的MIME类型。
        for (int i = 0; i < MIME_MapTable.length; i++) {
            if (end.equals(MIME_MapTable[i][0]))
                type = MIME_MapTable[i][1];
        }
        return type;
    }




    private final String[][] MIME_MapTable = {
// {后缀名， MIME类型}
            {"doc", "application/msword"},
            {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {"xls", "application/vnd.ms-excel"},
            {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {"pdf", "application/pdf"},
            {"ppt", "application/vnd.ms-powerpoint"},
            {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {"txt", "text/plain"},
            {"wps", "application/vnd.ms-works"},
            {"jpg", "image/jpeg"},
            {"jpeg", "image/jpeg"},
            {"zip", "application/zip"},
            {"png", "image/png"},
            {"", "*/*"}
    };
}
